using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;

namespace PrivateEngine
{
	class Dependence
	{
		public int from;
		public int to;
		public string var;
		public string kind;
		public string vec;
		
		public void print()
		{
		  //Console.WriteLine("Var " + var + " From " + from + " To " + to + " Kind " + kind);
		}
		
	}
	
	public class PrivateAlg
	{
		public bool problem;
		public string deps_file;
		
		public string Privatizing (Loop_Item _loop)
		{
			// Read the file and display it line by line.
			problem = false;
			string line;
			string[] tab;
			int t_from, t_to;
			
			List<string> variables = new List<string>();
			List<string> _priv_variables = new List<string>();
			List<Dependence> deps = new List<Dependence>();
			List<Dependence> deps_copy = new List<Dependence>();
			
			
			// zrzut z petita opcje   -Fc -4 -g
			StreamReader file = new StreamReader(deps_file);
			while((line = file.ReadLine()) != null)
			{
			   //Console.WriteLine (line);
				if(line != "")
				{
			   line = line.Replace(":", "");
			   tab = line.Split((char[]) null, StringSplitOptions.RemoveEmptyEntries);
			   string tmp_var = tab[2];
				
				if(tmp_var == "vp1") tmp_var +="";
				
				if(tab[2] == null)
					Console.WriteLine("p");
				
				//sprawdz czy zaleznosc nalezy do petli
				t_from = Convert.ToInt32(tab[1]);
				t_to = Convert.ToInt32(tab[4]);
				
				if(!(_loop.statements.Contains(t_from) && _loop.statements.Contains(t_to))) //zaleznosc nie zachodzi w ciele petli
					continue;
				
				
				
				//foreach(string s in tab)
				//	Console.WriteLine(s);
				
				//Console.WriteLine (tab[0]);
				if(tab[2] != tab[5])  //sprawdz jeszcze
				{
					tmp_var = CheckArr(tab[2], tab[5]);
				}
				
				Dependence d = new Dependence();
				d.from = Convert.ToInt32(tab[1]);
				d.to = Convert.ToInt32(tab[4]);
				d.kind = tab[0];
				d.vec = tab[6];
				d.var = tmp_var;
				
				d.print();
				
				
				if(d.kind == "reduce") problem = true;
				
				deps.Add(d);

				
				if(!variables.Contains(tmp_var))
					variables.Add(tmp_var);
				
			}
			}
			
			if(problem)
				return "BAD";
			
			if(deps.Count == 0) // nie ma zaleznosci
				return "OK";
		
		/*	if(_loop.address == "1;1;1;"){
					Console.WriteLine("------");
							foreach(Dependence d in deps)
					d.print();
			System.Environment.Exit(1);	
				Console.WriteLine("p");
			}
		*/	
			//analyse 
		foreach(string s in variables)
			{
				
				//Console.WriteLine("Analysing " + s);
				//int min = FindMin(deps, s);
				
				//Console.WriteLine(min.ToString());
				
				if(Private(deps, s, FindMin(deps, s)))
				{
				//	Console.WriteLine("Private " + s + " is allowed");
									
				}
				else 
				{
				    foreach(Dependence d in deps)
						if(d.var == s)
							deps_copy.Add(d);
					
				}		

			}
			
			//usun powtarzajace sie nazwy tablic
			if(deps_copy.Count == 0)
			{
			    string tmp; 
				bool dodaj;
				for(int i = 0; i < variables.Count; i++)
				{
				    dodaj = true;
					tmp = variables[i];
				//	Console.WriteLine(variables[i]);
					if(variables[i].Contains("("))
					{
						tmp = variables[i].Substring(0, variables[i].IndexOf("("));
						for(int j = 0; j < _priv_variables.Count; j++)
							if(tmp == _priv_variables[j])
								dodaj = false;
							
					}	
					if(dodaj)
						_priv_variables.Add(tmp);
					   
					
				}
					
				
			}
			else
				return "BAD";
			
		//	string priv = "";
			for(int i = 0; i < _priv_variables.Count; i++)
			{
				bool dodaj = false;
			//	string z = _priv_variables[i];
				
					foreach(Dependence dd in deps)
					{
						int ilep = dd.vec.Length - dd.vec.Replace(",", "").Length;
						string tmp = dd.var;
						
						if(tmp.Contains("("))
						{
							tmp = dd.var.Substring(0, dd.var.IndexOf("("));
						}
					
						if(_priv_variables[i] == tmp)
							if(!(ilep == _loop.level-1 && dd.vec.Contains(",0)")))
								dodaj = true;

						
					}
					
		
				if(dodaj)
				_loop.Add_index(_priv_variables[i]);
				//	priv += _priv_variables[i];
			//    if(i < 	_priv_variables.Count - 1)
			//		priv += ", ";
			//	else
				//	priv += ")";
			}
			
		/*	if(deps_copy.Count == 0)
			{
			//	Console.WriteLine("Privatization ok, all dependences removed");
			//	Console.WriteLine("-----");
			//	Console.WriteLine("");
				
			//	Console.WriteLine(priv);
			}
			else
				foreach(Dependence d in deps_copy)
					d.print();
				
		*/	

			file.Close();
		

			//if(deps_copy.Count == 0)
			return "OK";
			

		}
		
		private int FindMin(List<Dependence> deps, string var)
		{
			int min = int.MaxValue;
			foreach(Dependence d in deps)
			{
				if(d.var == var)	
				{
					min = d.from < min ? d.from : min;
					min = d.to < min ? d.to : min;
				}
			}
			
			return min;
			
		}
		
		private bool Private(List<Dependence> deps, string var, int min)
		{
			foreach(Dependence d in deps)
			{
				if(d.var == var && d.kind == "anti")	
				{
					if(d.from == min)
						return false;
				}
			}
			
			return true; //ok
			
		}
		
		private string CheckArr(string f, string t)
		{
			  //sprawdz czy a(1,2) -> a(1,m) to daj a(1,2) jak nie to przerwij
			
					if(f.Contains("...") || t.Contains("..."))
					{
				 problem = true; //ni da rady
				return null;
				}

					string _from_vec = f.Substring(f.IndexOf("(")+1, f.IndexOf(")")-f.IndexOf("(")-1);
					string _to_vec = t.Substring(t.IndexOf("(")+1, t.IndexOf(")")-t.IndexOf("(")-1);
					
					_from_vec = _from_vec.Replace("," , "");
					_from_vec = _from_vec.Replace(" " , "");
					_to_vec = _to_vec.Replace("," , "");
					_to_vec = _to_vec.Replace(" " , "");
					
					bool _from = true;
					bool _to = true;
					foreach(Char c in _from_vec)
						if(!Char.IsDigit(c))
							_from = false;
					
					foreach(Char c in _to_vec)
						if(!Char.IsDigit(c))
							_to = false;
			
					if(!_from && !_to)	
                   		 problem = true; //ni da rady
					
					if(_from)
						return f;
					
					if(_to)
						return t;
			
				return null;

		}
	}	
		
		
}


